package com.frame.work.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frame.work.common.constant.Const;
import com.frame.work.common.constant.DataType;
import com.frame.work.common.constant.TypeEnum;
import com.frame.work.common.util.Time;
import com.frame.work.entity.*;
import com.frame.work.entity.relation.TblGateWayHomeUserMessage;
import com.frame.work.entity.relation.TblZigbeeAndGateway;
import com.frame.work.mapper.TblDeviceActionsMapper;
import com.frame.work.mapper.TblDeviceMapper;
import com.frame.work.mapper.TblGatewayMapper;
import com.frame.work.mqtt.data.handle.MqttDataHandle;
import com.frame.work.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author wjming
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class TblDeviceImpl extends ServiceImpl<TblDeviceMapper, TblDevice> implements TblDeviceService {

    private final TblDeviceMapper deviceMapper;
    private final TblDeviceActionsMapper deviceActionsMapper;
    private final TblMeteringLogService meteringLogService;
    private final RedisTemplate redisTemplate;
    private final MqttDataHandle mqttDataHandle;
    private final TblDeviceTypeService deviceTypeService;
    private final JpushService jPushService;
    private final ZigbeeDevicePropertyService zigbeeDevicePropertyService;
    private final TblGatewayMapper gatewayMapper;

    @Override
    public void updateDevice(Map<String, Object> deviceMap, String gatewayMac) {
        try {
            TblZigbeeAndGateway tblDevice = getDeviceMessage(deviceMap.get("deviceMac").toString(), deviceMap.get("odIndex").toString(),
                    deviceMap.get("deviceType").toString(), deviceMap.get("productType").toString());

            //设备存在(修改设备属性)
            if (tblDevice != null && tblDevice.getGatewayMac().equals(deviceMap.get("gatewayMac"))) {
                //保存设备Action
                if (DataType.ZigbeeDevice.OD_0FAA.equals(deviceMap.get("odIndex")) && "02".equals(deviceMap.get("deviceType"))
                        && "11".equals(deviceMap.get("productType")) && "04".equals(deviceMap.get("switchState"))) {
                    Map<String, Object> actions = (Map<String, Object>) deviceMap.get("actions");
                    actions.put("switchState", tblDevice.getSwitchState());
                    deviceMap.put("actions", actions);
                }
                TblDevice device = new TblDevice();
                device.setSwitchTime(LocalDateTime.now());
                device.setSwitchState(deviceMap.get("switchState") != null ? deviceMap.get("switchState").toString() : null);
                device.setSpreadingType(deviceMap.get("spreadingType") != null ? deviceMap.get("spreadingType").toString() : null);
                device.setLwbz("0");
                device.setId(tblDevice.getId());
                int updateById = deviceMapper.updateById(device);
                //删除设备的Action信息
                if (deviceMap.get("actions") != null) {
                    deviceActionsMapper.delete(Wrappers.<TblDeviceActions>lambdaQuery()
                            .eq(TblDeviceActions::getDeviceId, tblDevice.getId()));
                }

                //组合Action
                Map<String, Object> actions = (Map<String, Object>) deviceMap.get("actions");

                List<TblDeviceActions> deviceActions = new ArrayList<>();
                for (Map.Entry<String, Object> entry : actions.entrySet()) {
                    TblDeviceActions tblDeviceActions = new TblDeviceActions();
                    tblDeviceActions.setActionsKey(entry.getKey());
                    tblDeviceActions.setActionsValue(entry.getValue() != null ? entry.getValue().toString() : null);
                    tblDeviceActions.setDeviceId(tblDevice.getId());
                    deviceActions.add(tblDeviceActions);
                }
                int insert = -1;
                if (deviceActions.size() > 0) {
                    insert = deviceActionsMapper.batchInsert(deviceActions);
                }

                if (insert < 1 && deviceActions.size() > 0) {
                    System.out.println("设备Action信息添加失败");
                }

                if (DataType.ZigbeeDevice.OD_0FC8.equals(deviceMap.get("odIndex")) && "04".equals(deviceMap.get("deviceType"))
                        && ("02".equals(deviceMap.get("productType")) || "03".equals(deviceMap.get("productType")))) {
                    Object message = redisTemplate.opsForValue().get("meteringLog_" + deviceMap.get("deviceMac"));
                    if (message == null || message == "") {
                        //获取电量
                        Double dianliang = Double.parseDouble(actions.get("dianliang") == null ? "0" : actions.get("dianliang").toString());
                        //获取电压
                        Double dianya = Double.parseDouble(actions.get("dianya") == null ? "0" : actions.get("dianya").toString());
                        //获取电流
                        Double dianliu = Double.parseDouble(actions.get("dianliu") == null ? "0" : actions.get("dianliu").toString());
                        //获取功率
                        Double gonglv = Double.parseDouble(actions.get("gonglv") == null ? "0" : actions.get("gonglv").toString());

                        TblGateWayHomeUserMessage zigbeeGateHomeMessage = deviceMapper.selectZigbeeGatewayAndHome(deviceMap.get("gatewayMac").toString());
                        TblMeteringLog tblMeteringLog = TblMeteringLog.builder().gatewayMac(deviceMap.get("gatewayMac").toString()).zigbeeMac(deviceMap.get("deviceMac").toString())
                                .electricQuantity(dianliang).userId(zigbeeGateHomeMessage.getAppUserId())
                                .voltage(dianya).current(dianliu).power(gonglv).build();
                        meteringLogService.addMeteringLog(tblMeteringLog);
                        redisTemplate.opsForValue().set("meteringLog_" + deviceMap.get("deviceMac"), actions.get("dianliang").toString(), 50, TimeUnit.MINUTES);
                    }
                }
            } else { //设备不存在或者设备不同再一个网关(开启自动入网抢设备的时候用)
                TblGateWayHomeUserMessage zigbeeGateHomeMessage = deviceMapper.selectZigbeeGatewayAndHome(deviceMap.get("gatewayMac").toString());
                if (zigbeeGateHomeMessage == null) {
                    System.out.println("网关未保存");
                }
                if (zigbeeGateHomeMessage != null && zigbeeGateHomeMessage.getZdrwbz().equals("Y")) {

                    ProductInfoApp deviceInfo = deviceTypeService.getOneById(deviceMap.get("odIndex").toString() + deviceMap.get("deviceType").toString() + deviceMap.get("productType").toString());
                    String ls_name = deviceInfo.getProductName();
                    String ls_imgurl = deviceInfo.getPZUrl();
                    //删除
                    deviceMapper.delete(Wrappers.<TblDevice>lambdaQuery().eq(TblDevice::getZigbeeMac, deviceMap.get("deviceMac"))
                            .eq(TblDevice::getOdIndex, deviceMap.get("odIndex")).eq(TblDevice::getDeviceType, deviceMap.get("deviceType"))
                            .eq(TblDevice::getProductType, deviceMap.get("productType")));

                    TblDevice device = TblDevice.builder().gatewayId(zigbeeGateHomeMessage.getId())
                            .zigbeeMac(deviceMap.get("deviceMac").toString()).odIndex(deviceMap.get("odIndex").toString())
                            .deviceType(deviceMap.get("deviceType").toString()).productType(deviceMap.get("productType").toString()).name(ls_name).imgUrl(ls_imgurl).build();
                    int insert1 = 0;
                    int insert2 = 0;

                    if (deviceMap.get("spreadingType") == null) {
                        insert1 = deviceMapper.insert(device);
                    } else {
                        device.setSpreadingType(deviceMap.get("spreadingType").toString());
                        insert2 = deviceMapper.insert(device);
                    }

                    if (insert1 > 0 || insert2 > 0) {
                        String typeCode = device.getOdIndex() + device.getDeviceType() + device.getProductType();
                        if (typeCode.equalsIgnoreCase("0FAA8A0A")) {
                            Map<String, Object> property = new HashMap<>(2);
                            String sceneCount = ((Map<String, String>) deviceMap.get("actions")).get("sceneCount");
                            String switchCount = ((Map<String, String>) deviceMap.get("actions")).get("switchCount");
                            property.put("sceneCount", Integer.parseInt(sceneCount));
                            property.put("switchCount", Integer.parseInt(switchCount));

                            TblZigbeeDeviceProperty zigbeeDeviceProperty = new TblZigbeeDeviceProperty();
                            zigbeeDeviceProperty.setId(device.getId());
                            zigbeeDeviceProperty.setProperty(JSONObject.toJSONString(property));
                            zigbeeDevicePropertyService.save(zigbeeDeviceProperty);
                        }
                    }

                    //设备如果添加成功了就发推送
                    if (insert1 > 0 || insert2 > 0) {
                        if (StringUtils.isNotEmpty(zigbeeGateHomeMessage.getSourceId())) {
                            deviceMap.put("id", device.getId());
                            deviceMap.put("gatewayId", zigbeeGateHomeMessage.getId());
                            deviceMap.put("name", ls_name);
                            deviceMap.put("imgUrl", ls_imgurl);
                            deviceMap.put("createTime", Time.NowTimeToMilliSecond());
                            deviceMap.put("modifyTime", Time.NowTimeToMilliSecond());
                            deviceMap.put("nowTime", Time.NowTimeToMilliSecond());
                            deviceMap.put("switchTime", Time.NowTimeToMilliSecond());

                            Map<String, Object> deviceMapCopy = new HashMap<>();
                            deviceMapCopy.putAll(deviceMap);

                            Object actions = deviceMapCopy.get("actions");
                            String jsonString = null;
                            if (actions != null) {
                                jsonString = JSONObject.toJSONString(deviceMapCopy.get("actions"));
                            }
                            deviceMapCopy.put("actions", jsonString);
                            String extrasObJson = JSONObject.toJSONString(deviceMapCopy);

                            try {
                                jPushService.send("", ls_name + "加入到" + zigbeeGateHomeMessage.getHomeName() + "的网关中", TypeEnum.DEVICE_TYPE.code(),
                                        zigbeeGateHomeMessage.getSourceId(),
                                        Const.extrasCode.IN_GATWAY, extrasObJson, zigbeeGateHomeMessage.getAppUserId(), zigbeeGateHomeMessage.getSourceType(),
                                        zigbeeGateHomeMessage.getOrganizationCode(), true);
                            } catch (Exception e) {
                                log.error("[TblDeviceImpl] ->[updateDevice推送异常]-> [userId:{}]->[e:{}]>", zigbeeGateHomeMessage.getAppUserId(), e.getMessage());
                            }

                        }
                    }
                    updateDevice(deviceMap, gatewayMac);
                }

            }
        } catch (Exception e) {
            log.error("[TblDeviceImpl] ->[updateDevice方法处发生异常]->[gatewayMac:{},deviceMap:{}] ->[e:{}]>", gatewayMac, JSONObject.toJSONString(deviceMap), e.getMessage());
        }
    }

    @Override
    public void lianKongDeviceHandle(Map<String, Object> deviceMap, String gatewayMac) {
        String deviceMac = deviceMap.get("deviceMac").toString();
        String odIndex = deviceMap.get("odIndex").toString();
        String deviceType = deviceMap.get("deviceType").toString();
        String productType = deviceMap.get("productType").toString();
        TblZigbeeAndGateway tblDevice = getDeviceMessage(deviceMac, odIndex, deviceType, productType);
        String getDeviceLianKongMessage = new StringBuilder().append(deviceMac).append("_").append(odIndex).append(deviceType).append(productType).toString();
        Object o = redisTemplate.opsForValue().get("push_" + getDeviceLianKongMessage);
        if (tblDevice != null && StringUtils.isNotEmpty(tblDevice.getSwitchState()) && tblDevice.getSwitchState().equals(deviceMap.get("switchState")) && o == null) {
            if ("1".equals(tblDevice.getLwbz())) {
                mqttDataHandle.basePush(gatewayMac, JSONObject.toJSONString(deviceMap));
                redisTemplate.opsForValue().set(getDeviceLianKongMessage, "push", 1, TimeUnit.MINUTES);
            }
        } else {
            mqttDataHandle.basePush(gatewayMac, JSONObject.toJSONString(deviceMap));
        }
        updateDevice(deviceMap, gatewayMac);
    }


    @Override
    public void updateDeviceScene(Map<String, Object> messageObj) {
        TblDevice tblDevice = deviceMapper.selectOne(Wrappers.<TblDevice>lambdaQuery()
                .eq(TblDevice::getZigbeeMac, messageObj.get("deviceMac"))
                .eq(TblDevice::getOdIndex, messageObj.get("odIndex"))
                .eq(TblDevice::getDeviceType, messageObj.get("deviceType"))
                .eq(TblDevice::getProductType, messageObj.get("productType")));
        //设备已经存在保存设备action
        if (tblDevice != null) {
            TblDevice build = TblDevice.builder().switchState("0").build();
            build.setId(tblDevice.getId());
            int updateById = deviceMapper.updateById(build);
        }
    }


    private TblZigbeeAndGateway getDeviceMessage(String deviceMac, String odIndex, String deviceType, String productType) {
        QueryWrapper<TblDevice> queryWrapper = new QueryWrapper();
        queryWrapper.eq("t_d.zigbee_mac", deviceMac);
        queryWrapper.eq("t_d.od_index", odIndex);
        queryWrapper.eq("t_d.device_type", deviceType);
        queryWrapper.eq("t_d.product_type", productType);
        return deviceMapper.selectOneByMac(queryWrapper);
    }

    /**
     * 判断设备状态是否一致，用于检测防拆开关是否被拆
     *
     * @param deviceMac
     * @param state
     * @return
     */
    @Override
    public boolean judgeState(String deviceMac, String state) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("zigbee_mac", deviceMac);
        TblDevice tblDevice = this.deviceMapper.selectOne(queryWrapper);
        if (state.equals(tblDevice.getSwitchState())) {
            return true;
        } else {
            return false;
        }

    }

    @Override
    public TblDevice selectDeviceByMac(String deviceMac) {
        return getOne(Wrappers.<TblDevice>lambdaQuery().eq(TblDevice::getZigbeeMac, deviceMac));
    }

    @Override
    public void resetMeterLog(String deviceMac) {
        TblDevice tblDevice = selectDeviceByMac(deviceMac);
        if (tblDevice == null) {
            return;
        }

        String type = tblDevice.getOdIndex() + tblDevice.getDeviceType() + tblDevice.getProductType();
        switch (type) {
            case "0FC80402":
            case "0FC80403":
                System.out.println("重置");
                //删除记录
                meteringLogService.deleteAllByDeviceMac(deviceMac);

                //添加一条新纪录
//                String gatewayMacById = selectGatewayMacById(tblDevice.getGatewayId());
//                TblGateWayHomeUserMessage tblGateWayHomeUserMessage = deviceMapper.selectZigbeeGatewayAndHome(gatewayMacById);
//                String appUserId = tblGateWayHomeUserMessage.getAppUserId();
//                TblMeteringLog tblMeteringLog = TblMeteringLog.builder().gatewayMac(gatewayMacById).zigbeeMac(deviceMac)
//                        .electricQuantity(0.00).userId(appUserId)
//                        .voltage(233.40).current(0.00).power(0d).build();
//                meteringLogService.addMeteringLog(tblMeteringLog);
//                redisTemplate.opsForValue().set("meteringLog_" + deviceMac, "0", 50, TimeUnit.MINUTES);
                break;
            default:
                break;
        }
    }

    String selectGatewayMacById(String gatewayId) {
        TblGateway tblGateway = gatewayMapper.selectById(gatewayId);
        return tblGateway == null ? "" : tblGateway.getZigbeeMac();
    }

}
